<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    
  </style>
</head>
<body>
  
</body>
<script>

  // 自定义事件系统
  function MyEvent(){
    // 用来记录将来可能出现的行为及对应的处理函数
    // this.message = {
    //   abc: [fn4],
    //   qwe: [fn2, fn4, fn1]
    // }
    this.message = {};
    // 绑定信息标志和处理函数
    this.on = function(type, cb){
      // 初始判断信息记录中是否存在当前信息标志
      if(this.message[type]){
        // 如果已经存在，向对应的数组中添加新值
        this.message[type].push(cb);
      }else{
        // 如果不存在，添加该信息标志，并设置数组为当前值
        this.message[type] = [cb];
      }
    }
    // 解绑信息标志和处理函数
    this.off = function(type, cb){
      // 确认当前信息标志存在，如果不存在，无需删除
      if(!this.message[type]) return;
      // 从信息记录的数组中获取当前处理函数的索引
      const index = this.message[type].indexOf(cb);
      // 确认找到该处理函数了
      if(index !== -1){
        // 删除
        this.message[type].splice(index, 1);
      }
    }
    // 触发某个信息，执行该信息对应的处理函数
    this.emit = function(type){
      // 触发之前先判断是否存在该信息标志
      if(!this.message[type]) return;
      // 如果存在，读取该信息标志的所有的处理函数，并遍历
      this.message[type].forEach(val=>{
        // 执行
        val();
      })
    }
  }

  // 创建一个发布订阅系统
  const event = new MyEvent();

  // 绑定，建立发布者和订阅者之间的关系
  event.on("abc", fn1);
  event.on("abc", fn3);
  event.on("abc", fn4);

  event.on("qwe", fn2);
  event.on("qwe", fn4);
  event.on("qwe", fn1);

  // 删除，解除发布者和订阅者之间的关系
  event.off("abc", fn3);

  // 发布信息
  event.emit("abc");
  event.emit("qwe");
  event.emit("asd");





  function fn1(){
    console.log(1)
  }
  function fn2(){
    console.log(2)
  }
  function fn3(){
    console.log(3)
  }
  function fn4(){
    console.log(4)
  }
  
</script>
</html>